package com.dragon.mmochat.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dragon.mmochat.MmochatConstant;
import com.dragon.mmochat.MmochatMain;
import com.dragon.mmochat.message.Mmochat_2_1C;
import com.dragon.mmochat.message.Mmochat_2_2S;
import com.dragon.mmochat.message.Mmochat_2_3C;
import com.dragon.mmochat.message.Mmochat_2_3S;
import com.dragon.mmochat.message.Mmochat_2_8S;
import com.dragon.mmochat.message.Mmochat_2_9C;
import com.dragon.mmochat.model.MmochatTeam;
import com.dragon.mmochat.model.attackMode.MmochatAttackModeOfNormal;
import com.dragon.mmochat.model.enumType.MmochatBattleType;
import com.dragon.mmochat.model.enumType.MmochatBossLevelType;
import com.dragon.mmochat.model.enumType.MmochatPropType;
import com.dragon.mmochat.model.enumType.MmochatRoleAttributeType;
import com.dragon.mmochat.model.enumType.MmochatRoleBmpType;
import com.dragon.mmochat.model.enumType.MmochatRoleType;
import com.dragon.mmochat.model.enumType.MmochatShowRoleSet;
import com.dragon.mmochat.model.enumType.MmochatTaskType;
import com.dragon.mmochat.model.enumType.MmochatTeamStateType;
import com.dragon.mmochat.model.map.MmochatMap;
import com.dragon.mmochat.model.map.MmochatMovePoint;
import com.dragon.mmochat.model.role.MmochatMonster;
import com.dragon.mmochat.model.role.MmochatMonsterFactory;
import com.dragon.mmochat.model.role.MmochatNpc;
import com.dragon.mmochat.model.role.MmochatPlayer;
import com.dragon.mmochat.util.MmochatUtil;
import com.skymobi.handler.SkymobiHandler;
import com.skymobi.message.SkymobiProtocolMessage;
import com.skymobi.service.SkymobiService;

public class MmochatMotionService {
	private static Logger log = LoggerFactory
			.getLogger(MmochatMotionService.class);
	// 定时下发需要弥补的角色信息,每条线对应一个线程
	public static ScheduledExecutorService es_line = Executors
			.newScheduledThreadPool(10);

	// 定时下发移动线程
	public static ScheduledExecutorService sendMotionThread = Executors
			.newScheduledThreadPool(1);

	public static int[] checkSceenTags = new int[20];

	public static int sendMotionTags = 0;

	public void init() {
		if (!MmochatMain.openMergeServer) {
			for (int i = 0; i < 20; i++) {
				checkSceenTags[i] = 0;
			}
			int interval = 1;
			es_line.scheduleWithFixedDelay(new CheckSceen(0), interval,
					interval, TimeUnit.SECONDS);
			es_line.scheduleWithFixedDelay(new CheckSceen(1), interval,
					interval, TimeUnit.SECONDS);
			es_line.scheduleWithFixedDelay(new CheckSceen(2), interval,
					interval, TimeUnit.SECONDS);
			es_line.scheduleWithFixedDelay(new CheckSceen(3), interval,
					interval, TimeUnit.SECONDS);
			es_line.scheduleWithFixedDelay(new CheckSceen(4), interval,
					interval, TimeUnit.SECONDS);
			es_line.scheduleWithFixedDelay(new CheckSceen(5), interval,
					interval, TimeUnit.SECONDS);
			es_line.scheduleWithFixedDelay(new CheckSceen(6), interval,
					interval, TimeUnit.SECONDS);
			es_line.scheduleWithFixedDelay(new CheckSceen(7), interval,
					interval, TimeUnit.SECONDS);
			es_line.scheduleWithFixedDelay(new CheckSceen(8), interval,
					interval, TimeUnit.SECONDS);
			es_line.scheduleWithFixedDelay(new CheckSceen(9), interval,
					interval, TimeUnit.SECONDS);

			sendMotionThread.scheduleWithFixedDelay(new SendMotion(), 500, 500,
					TimeUnit.MILLISECONDS);// 1秒钟2次，3秒钟6次
		}
	}

	// 定时下发移动
	class SendMotion implements Runnable {
		@Override
		public void run() {
			try {
				sendMotionTags++;
				if (sendMotionTags >= 6) {
					sendMotionTags = 0;
				}
				int curTag = sendMotionTags; // 0~5
				//log.debug("SendMotion curTag=" + curTag);

				for (MmochatPlayer player : MmochatMainService.players.values()) {
					if (player.getRoleId() % 6 != curTag) {
						// 每隔3秒会有一次下发机会
						continue;
					}
					if (player.isMicroNetFlowMode()) {
						continue;
					}
					if (player.getPositionBuffer().size() == 0) {
						continue;
					}
					if (!player.canReceiveMotionInfo()) {
						continue;
					}
					player.setLastTimeOfReceiveMotionData(System
							.currentTimeMillis());
					// TODO:过滤无效项
					for (MmochatMovePoint move : player.getPositionBuffer()
							.values()) {
						// 当角色已经离开游戏或换地图或换线，则直接清除而不下发
						MmochatPlayer he = MmochatMainService.players.get(move
								.getPlayer().getRoleId());
						if (he == null || he.getMapId() != player.getMapId()
								|| he.getLine() != player.getLine()) {
							player.getPositionBuffer().remove(
									move.getPlayer().getRoleId());
						}
					}

					if (player.getPositionBuffer().size() <= MmochatConstant.maxRoleNumToMove) {
						// 未超过下发限额，全数下发
						Mmochat_2_2S pack = new Mmochat_2_2S();
						pack.setMapId(player.getMapId());
						pack.setLine((byte) player.getLine());
						pack.setMoves(new ArrayList<MmochatMovePoint>(player
								.getPositionBuffer().values()));
						pack.setMe(player);
						MmochatUtil.sendCommonPack(MmochatHandle_SendMotion
								.getCommonHandler(), player, pack);
						player.getPositionBuffer().clear();
					} else {
						// 优先选取好友下发
						// 乱序排序
						List<MmochatMovePoint> moveList = MmochatUtil
								.messList(new ArrayList<MmochatMovePoint>(
										player.getPositionBuffer().values()));

						List<MmochatMovePoint> moves = new ArrayList<MmochatMovePoint>();
						// 50%的名额给好友
						for (MmochatMovePoint move : moveList) {
							if (player.getMyDearFriends().get(
									move.getPlayer().getRoleId()) != null) {
								moves.add(move);
								player.getPositionBuffer().remove(
										move.getPlayer().getRoleId());
								if (moves.size() >= MmochatConstant.maxRoleNumToMove / 2) {
									break;
								}
							}
						}
						// 50%的名额给剩下未选中的(可以是好友)
						if (moves.size() < MmochatConstant.maxRoleNumToMove) {
							for (MmochatMovePoint move : moveList) {
								if (!moves.contains(move)) {
									moves.add(move);
									player.getPositionBuffer().remove(
											move.getPlayer().getRoleId());
									if (moves.size() >= MmochatConstant.maxRoleNumToMove) {
										break;
									}
								}
							}
						}
						// 影像同步
						for (MmochatMovePoint move : moves) {
							if (Math.abs(move.getPlayer().getX()
									- player.getX()) >= MmochatConstant.screenWidth
									|| Math.abs(move.getPlayer().getY()
											- player.getY()) >= MmochatConstant.screenHeight) {
								// 移动后不在视界范围内
								player.delSceenRole(move.getPlayer()
										.getRoleId());
							} else {
								// 移动后在视界范围内
								player.addSceenRole(move.getPlayer()
										.getRoleId(), move.getPlayer()
										.getStateValue(player));
							}
						}
						Mmochat_2_2S pack = new Mmochat_2_2S();
						pack.setMapId(player.getMapId());
						pack.setLine((byte) player.getLine());
						pack.setMoves(moves);
						pack.setMe(player);
						MmochatUtil.sendCommonPack(MmochatHandle_SendMotion
								.getCommonHandler(), player, pack);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	// 定时下发需要弥补的角色信息
	class CheckSceen implements Runnable {
		int line = 0;

		public CheckSceen(int i) {
			line = i;
		}

		@Override
		public void run() {
			try {
				long t = System.currentTimeMillis();
				if (line >= MmochatConstant.maxMapLineNum) {
					return;
				}
				checkSceenTags[line]++;
				if (checkSceenTags[line] >= 4) {
					checkSceenTags[line] = 0;
				}
				int curTag = checkSceenTags[line]; // 0,1,2,3
				//log.debug(line + "线,tag=" + curTag);
				int delRoleNum, addRoleNum, delNpcNum, addNpcNum;
				for (MmochatMap map : MmochatMapService.maps.values()) {
					for (MmochatPlayer me : map.getLineRoleMap(line).values()) {
						if (me.getRoleId() % 4 != curTag) {
							// 每隔4秒会有一次下发机会
							continue;
						}
						if (me.isMicroNetFlowMode()) {
							continue;
						}
						if (me.isInBattle() || me.isInWatchingBattle()) {
							continue;
						}
						delRoleNum = 0;
						addRoleNum = 0;
						delNpcNum = 0;
						addNpcNum = 0;
						List<Integer> delRoleIds = new ArrayList<Integer>();
						List<MmochatPlayer> addRoles = new ArrayList<MmochatPlayer>();
						List<MmochatPlayer> modifyRoles = new ArrayList<MmochatPlayer>();
						List<Integer> delNpcIds = new ArrayList<Integer>();
						List<MmochatNpc> addNpcs = new ArrayList<MmochatNpc>();

						// 计算需要删除和修改的玩家结点
						for (Entry<Integer, Long> entry : me.getSceenRoles()
								.entrySet()) {
							int roleId = entry.getKey();
							long oldState = entry.getValue();
							try {
								MmochatPlayer other = map.getLineRoleMap(line)
										.get(roleId);
								if (other != null
										&& me.getRoleId() != other.getRoleId()) {
									if (Math.abs(me.getX() - other.getX()) < MmochatConstant.screenWidth
											&& Math.abs(me.getY()
													- other.getY()) < MmochatConstant.screenHeight) {
										// 在屏幕范围内
										boolean delete = false;
										if (me.isInTeam()
												&& me.getTeamId() == other
														.getTeamId()) {
											// 同在一队，则显示
											delete = false;
										} else if (me.getShowRoleSet() == MmochatShowRoleSet.隐藏所有人) {
											delete = true;
										} else if (me.getShowRoleSet() == MmochatShowRoleSet.只显示队长) {
											if (MmochatTeamService
													.getTeamState(other) != MmochatTeamStateType.队长) {
												delete = true;
											}
										} else if (me.getShowRoleSet() == MmochatShowRoleSet.只显示好友) {
											if (me.getMyDearFriends().get(
													other.getRoleId()) == null) {
												delete = true;
											}
										} else if (me.getMyEnermys().get(
												other.getRoleId()) != null) {
											// 黑名单中的人
											delete = true;
										}
										if (!delete) {
											// 要修改的玩家结点
											if (modifyRoles.size() < MmochatConstant.maxStateNumToModifyAfterMove) {
												if (oldState != other
														.getStateValue(me)) {
													modifyRoles.add(other);
													me
															.getSceenRoles()
															.put(
																	roleId,
																	other
																			.getStateValue(me));
												}
											}
											continue;
										}
									}
								}
								// 角色已经离开视界范围,换线或离线,删除结点
								if (delRoleNum < MmochatConstant.maxRoleNumToDeleteAfterMove) {
									delRoleIds.add(roleId);
									me.delSceenRole(roleId);
									delRoleNum++;
								}
								if (modifyRoles.size() >= MmochatConstant.maxStateNumToModifyAfterMove
										&& delRoleNum >= MmochatConstant.maxRoleNumToDeleteAfterMove) {
									break;
								}
							} catch (Exception e) {
								e.printStackTrace();
							}

						}

						// 计算需要增加的玩家结点
						for (MmochatPlayer newRole : map.getLineRoleMap(line)
								.values()) {
							try {
								if (me.getRoleId() == newRole.getRoleId()) {
									continue;
								}
								boolean mustShow = false;
								if (me.isInTeam()
										&& me.getTeamId() == newRole
												.getTeamId()) {
									// 同在一队，则显示
									mustShow = true;
								}
								if (!mustShow
										&& me.getShowRoleSet() == MmochatShowRoleSet.隐藏所有人) {
									continue;
								}
								if (!mustShow
										&& me.getSceenRoles().size() >= me
												.getMax_screen_role_num()) {
									continue;
								}
								if (me.getMyEnermys().get(newRole.getRoleId()) != null) {
									// 黑名单中的人
									continue;
								}
								if (newRole.getRoleId() != me.getRoleId()) {
									if (!me.getSceenRoles().containsKey(
											newRole.getRoleId())) {
										if (Math
												.abs(me.getX() - newRole.getX()) < MmochatConstant.screenWidth
												&& Math.abs(me.getY()
														- newRole.getY()) < MmochatConstant.screenHeight) {
											// 新进入视界的角色
											if (!mustShow) {
												if (me.getShowRoleSet() == MmochatShowRoleSet.只显示队长) {
													if (MmochatTeamService
															.getTeamState(newRole) != MmochatTeamStateType.队长) {
														continue;
													}
												}
												if (me.getShowRoleSet() == MmochatShowRoleSet.只显示好友) {
													if (me
															.getMyDearFriends()
															.get(
																	newRole
																			.getRoleId()) == null) {
														continue;
													}
												}
											}
											addRoles.add(newRole);
											me.addSceenRole(
													newRole.getRoleId(),
													newRole.getStateValue(me));
											addRoleNum++;
											if (addRoleNum >= MmochatConstant.maxRoleNumToAddAfterMove) {
												break;
											}
										}
									}
								}
							} catch (Exception e) {
								e.printStackTrace();
							}
						}

						// 计算需要删除的npc结点
						Map<Integer, MmochatNpc> lineNpcs = map
								.getLineNpcMap(line);
						for (Integer npcId : me.getTmpNpcs().keySet()) {
							try {
								if (lineNpcs.get(npcId) == null) {
									delNpcIds.add(npcId);
									me.delTmpNpc(npcId);
									delNpcNum++;
									if (delNpcNum >= MmochatConstant.maxNpcNumToDeleteAfterMove) {
										break;
									}
								}
							} catch (Exception e) {
								e.printStackTrace();
							}
						}

						// 计算需要增加的npc结点
						for (MmochatNpc npc : lineNpcs.values()) {
							try {

								if (me.getTmpNpcs().get(npc.getNpcId()) == null) {
									if (Math.abs(me.getX() - npc.getX()) < MmochatConstant.screenWidth
											&& Math.abs(me.getY() - npc.getY()) < MmochatConstant.screenHeight) {
										// 新进入视界的npc
										addNpcs.add(npc);
										me.addTmpNpc(npc.getNpcId());
										addNpcNum++;
										if (addNpcNum >= MmochatConstant.maxNpcNumToAddAfterMove) {
											break;
										}
									}

								}
							} catch (Exception e) {
								e.printStackTrace();
							}
						}

						// 分包下发
						if (delRoleNum > 0) {
							Mmochat_2_8S pack = new Mmochat_2_8S();
							pack.setMapId(map.getMapId());
							pack.setLine((byte) line);
							pack.setDelRoleIds(delRoleIds);
							pack.setMe(me);
							MmochatUtil.sendCommonPack(MmochatHandle_SendMotion
									.getCommonHandler(), me, pack);
						}

						if (addRoleNum > 0) {
							Mmochat_2_8S pack = new Mmochat_2_8S();
							pack.setMapId(map.getMapId());
							pack.setLine((byte) line);
							pack.setAddRoles(addRoles);
							pack.setMe(me);
							MmochatUtil.sendCommonPack(MmochatHandle_SendMotion
									.getCommonHandler(), me, pack);
						}

						if (delNpcNum > 0) {
							Mmochat_2_8S pack = new Mmochat_2_8S();
							pack.setMapId(map.getMapId());
							pack.setLine((byte) line);
							pack.setDelNpcIds(delNpcIds);
							pack.setMe(me);
							MmochatUtil.sendCommonPack(MmochatHandle_SendMotion
									.getCommonHandler(), me, pack);
						}

						if (addNpcNum > 0) {
							Mmochat_2_8S pack = new Mmochat_2_8S();
							pack.setMapId(map.getMapId());
							pack.setLine((byte) line);
							pack.setAddNpcs(addNpcs);
							pack.setMe(me);
							MmochatUtil.sendCommonPack(MmochatHandle_SendMotion
									.getCommonHandler(), me, pack);
						}

						if (modifyRoles.size() > 0) {
							Mmochat_2_8S pack = new Mmochat_2_8S();
							pack.setMapId(map.getMapId());
							pack.setLine((byte) line);
							pack.setModifyRoles(modifyRoles);
							pack.setMe(me);
							MmochatUtil.sendCommonPack(MmochatHandle_SendMotion
									.getCommonHandler(), me, pack);
						}
					}
				}
				if (MmochatConstant.testCheckSceen) {
					log.error("checkScreen,line:" + line + ",time="
							+ (System.currentTimeMillis() - t) + "ms");
				}
			} catch (Exception e) {
				log.debug("错误:定时下发需要弥补的角色信息");
				e.printStackTrace();
			}
		}
	}

	// 2.2 上传移动信息
	@SkymobiService
	public void handleC_2_1(SkymobiHandler handler, Mmochat_2_1C req) {
		MmochatPlayer me = MmochatMainService.getPlayerByRoleId(req, req
				.getRoleId());
		if (me == null) {
			return;
		}

		if (me.getMapId() != (int) req.getMapId()
				|| me.getLine() != (int) req.getLine()) {
			return;
		}
		short x = req.getX();
		short y = req.getY();

		MmochatMap curMap = MmochatMapService.maps.get(me.getMapId());
		if (curMap == null) {
			// TODO:地图不存在,将角色移到默认地图
			return;
		}
		int line = me.getLine();

		boolean isTeamLeader = false;
		List<MmochatPlayer> teamMembers = new ArrayList<MmochatPlayer>();
		if (me.isInTeam()) {
			MmochatTeam team = MmochatTeamService.teams.get(me.getTeamId());
			if (team == null) {
				me.leaveTeam();
			} else {
				if (!team.isTeamLeader(me.getRoleId())) {
					// 队长在下发移动坐标时，已经将全队的移动信息发给了所有人，所以队员不必再上传
					return;
				} else {
					isTeamLeader = true;
					for (Integer roleId : team.getMemberId().values()) {
						MmochatPlayer member = MmochatMainService.players
								.get(roleId);
						if (member != null) {
							teamMembers.add(member);
							member.setLastActionTime();
						}
					}
				}
			}
		}
		if (!me.isInTeam()) {
			teamMembers.clear();
			teamMembers.add(me);
		}

		// 向同地图内的同屏玩家下发移动信息
		for (MmochatPlayer role : curMap.getLineRoleMap(line).values()) {
			try {
				if (role.getRoleId() == me.getRoleId()
						&& teamMembers.size() == 1) {
					continue;
				} else {
					// 移动前同屏或者移动后同屏
					if (Math.abs(role.getX() - me.getX()) < MmochatConstant.screenWidth
							&& Math.abs(role.getY() - me.getY()) < MmochatConstant.screenHeight
							|| Math.abs(role.getX() - x) < MmochatConstant.screenWidth
							&& Math.abs(role.getY() - y) < MmochatConstant.screenHeight) {
						// 实际需要下发的人员
						Map<Integer, MmochatPlayer> teamMembers2 = new ConcurrentHashMap<Integer, MmochatPlayer>();
						for (MmochatPlayer member : teamMembers) {
							teamMembers2.put(member.getRoleId(), member);
						}

						if (Math.abs(role.getX() - x) >= MmochatConstant.screenWidth
								|| Math.abs(role.getY() - y) >= MmochatConstant.screenHeight) {
							// 移动后不同屏, 修改我队人员的终端环境影像(终端将同步删除role结点)
							for (MmochatPlayer member : teamMembers) {
								if (member.getRoleId() != role.getRoleId()) {
									member.delSceenRole(role.getRoleId());
									member.getPositionBuffer().remove(
											role.getRoleId());
								}
							}
						} else {
							// 移动后同屏
							if (!teamMembers.contains(role)) {
								for (MmochatPlayer member : teamMembers) {
									if (!role.getSceenRoles().containsKey(
											member.getRoleId())) {
										if (role.getSceenRoles().size() >= role
												.getMax_screen_role_num()) {
											// 此人终端同屏人数过多，无法再接收新人
											teamMembers2.remove(member
													.getRoleId());
										}
									}
								}
							}
						}

						if (!teamMembers.contains(role)) {
							// 非队员,则将消息放入坐标缓存器
							if (role.isMicroNetFlowMode()) {
								continue;
							}
							if (role.getMyEnermys().get(me.getRoleId()) != null) {
								// 在对方的黑名单中
								continue;
							} else if (role.getShowRoleSet() == MmochatShowRoleSet.隐藏所有人) {
								continue;
							} else if (role.getShowRoleSet() == MmochatShowRoleSet.只显示队长) {
								if (isTeamLeader) {
									if (teamMembers2.get(me.getRoleId()) != null) {
										MmochatMovePoint movePoint = new MmochatMovePoint();
										movePoint.setPlayer(me);
										movePoint.setX(x);
										movePoint.setY(y);
										movePoint.setPreStep(0);
										role.getPositionBuffer().put(
												me.getRoleId(), movePoint);
									}
								}
							} else if (role.getShowRoleSet() == MmochatShowRoleSet.只显示好友) {
								int index = 1;
								for (MmochatPlayer member : teamMembers2
										.values()) {
									if (role.getMyDearFriends().get(
											member.getRoleId()) == null) {
										if (member.getRoleId() != me
												.getRoleId()) {
											index++;
										}
										continue;
									}
									MmochatMovePoint movePoint = new MmochatMovePoint();
									if (member.getRoleId() == me.getRoleId()) {
										// 队长
										movePoint.setPreStep(0);
									} else {
										movePoint.setPreStep(index);
										index++;
									}
									movePoint.setX(x);
									movePoint.setY(y);
									movePoint.setPlayer(member);
									role.getPositionBuffer().put(
											member.getRoleId(), movePoint);
								}
							} else {
								int index = 1;
								for (MmochatPlayer member : teamMembers2
										.values()) {
									MmochatMovePoint movePoint = new MmochatMovePoint();
									if (member.getRoleId() == me.getRoleId()) {
										// 队长
										movePoint.setPreStep(0);
									} else {
										movePoint.setPreStep(index);
										index++;
									}
									movePoint.setX(x);
									movePoint.setY(y);
									movePoint.setPlayer(member);
									role.getPositionBuffer().put(
											member.getRoleId(), movePoint);
								}
							}
						} else {
							// 同队队员,则将坐标立即下发,以保证同队移动同步
							List<MmochatMovePoint> moves = new ArrayList<MmochatMovePoint>();
							int index = 1;
							for (MmochatPlayer member : teamMembers2.values()) {
								MmochatMovePoint movePoint = new MmochatMovePoint();
								if (member.getRoleId() == me.getRoleId()) {
									// 队长
									if (role.getRoleId() == me.getRoleId()) {
										continue;
									}
									movePoint.setPreStep(0);
								} else {
									movePoint.setPreStep(index);
									index++;
								}
								movePoint.setX(x);
								movePoint.setY(y);
								movePoint.setPlayer(member);
								moves.add(movePoint);
							}
							if (role.canReceiveMotionInfo()) {
								Mmochat_2_2S pack = new Mmochat_2_2S();
								pack.setMapId(curMap.getMapId());
								pack.setLine((byte) line);
								pack.setMoves(moves);
								pack.setMe(role);
								MmochatUtil.sendCommonPack(role, pack);
								role.setLastTimeOfReceiveMotionData(System
										.currentTimeMillis());
							}
						}
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		for (MmochatPlayer member : teamMembers) {
			member.setX(x);
			member.setY(y);
		}
	}

	// 2.3 请求roleId的角色信息,用以增加角色链
	@SkymobiService
	public SkymobiProtocolMessage handleC_2_3(SkymobiHandler handler,
			Mmochat_2_3C req) {
		MmochatPlayer myRole = MmochatMainService.getPlayerByRoleId(req, req
				.getMyRole());
		if (myRole == null) {
			return null;
		}

		if (myRole.getMapId() != (int) req.getMapId()
				|| myRole.getLine() != (int) req.getLine()) {
			return null;
		}

		int line = myRole.getLine();
		MmochatMap curMap = MmochatMapService.maps.get(myRole.getMapId());
		if (curMap == null) {
			// TODO:地图不存在,将角色移到默认地图
			return null;
		}
		MmochatPlayer role = curMap.getLineRoleMap(line).get(req.getRoleId());
		if (role == null) {
			return null;
		}
		Mmochat_2_3S pack = new Mmochat_2_3S();
		pack.setRole(role);
		pack.setMe(myRole);
		return pack;
	}

	// 2.9 走动遇怪
	@SkymobiService
	public void handleC_2_9(SkymobiHandler handler, Mmochat_2_9C req) {
		MmochatPlayer me = MmochatMainService.getPlayerByRoleId(req, req
				.getRoleId());
		if (me == null) {
			return;
		}

		if (me.isInBattle()) {
			log.debug("玩家" + me.getName() + "(skyid=" + me.getSkyId()
					+ ")已经在战斗中,无法遇怪");
			return;
		}
		if (me.getMapId() != (int) req.getMapId()
				|| me.getLine() != (int) req.getLine()) {
			log.debug("玩家" + me.getName() + "(skyid=" + me.getSkyId()
					+ ")终端位置与服务端不一致，无法遇怪;服务端mapId=" + me.getMapId() + ",line="
					+ me.getLine() + ",终端mapId=" + req.getMapId() + ",line="
					+ req.getLine());
			return;
		}

		if (me.isInTeam()) {
			MmochatTeam team = MmochatTeamService.teams.get(me.getTeamId());
			if (team != null) {
				if (!team.isTeamLeader(me.getRoleId())) {
					// 队员不遇怪
					log.debug("玩家" + me.getName() + "(skyid=" + me.getSkyId()
							+ ")在队伍中不是队长,无法带领队伍遇怪");
					return;
				}
			}
		}
		if (!me.isCanEnterBattle()) {
			return;
		}

		MmochatMap curMap = MmochatMapService.getMapByMapId(req.getMapId());
		if (curMap == null) {
			log.debug("玩家" + me.getName() + "(skyid=" + me.getSkyId()
					+ ")在未知地图,无法遇怪,mapId=" + req.getMapId());
			return;
		}

		// 道具:判断玩家是否使用了驱魔香
		if (me.hasPropEffect(MmochatPropType.龙涎香.getEffectKey())) {
			return;
		}
		if (me.hasPropEffect(MmochatPropType.驱魔符.getEffectKey())) {
			if (curMap.getMonster().size() > 0) {
				try {
					int monsterLevel = curMap.getMonster().get(0).getLevel();
					if (me.getLevel() + 10 >= monsterLevel) {
						return;
					}
				} catch (Exception e) {
					e.printStackTrace();
					return;
				}
			}
		}

		// 玩家队伍
		List<MmochatPlayer> myTeam = new ArrayList<MmochatPlayer>();
		if (me.isInTeam()) {
			MmochatTeam team = MmochatTeamService.teams.get(me.getTeamId());
			if (team == null) {
				me.leaveTeam();
				myTeam.add(me);
			} else {
				for (Integer roleId : team.getMemberId().values()) {
					MmochatPlayer member = MmochatMainService
							.getRoleFromBuffer(roleId);
					if (member != null) {
						myTeam.add(member);
					}
				}
			}
		} else {
			myTeam.add(me);
		}

		int teamNum = myTeam.size();
		if (teamNum == 0) {
			log.debug("玩家" + me.getName() + "(skyid=" + me.getSkyId()
					+ ")队伍总人数为0,无法遇怪");
			return;
		}

		// 怪物队伍
		// 道具:如果使用了满卡，则怪数量固定为2XteamNum
		int monsterNum = 0;
		if (me.hasPropEffect(MmochatPropType.顶级急急如律令.getEffectKey())) {
			monsterNum = teamNum * 5;
		} else if (me.hasPropEffect(MmochatPropType.特级急急如律令.getEffectKey())) {
			monsterNum = (int) (teamNum * 3.4);
		} else if (me.hasPropEffect(MmochatPropType.超级急急如律令.getEffectKey())) {
			monsterNum = (int) (teamNum * 2.5);
		} else if (me.hasPropEffect(MmochatPropType.急急如律令.getEffectKey())) {
			monsterNum = teamNum * 2;
		} else {
			monsterNum = teamNum + (int) (Math.random() * (teamNum + 1));
		}
		monsterNum = Math.min(10, monsterNum);
		if (monsterNum == 0) {
			log.debug("玩家" + me.getName() + "(skyid=" + me.getSkyId()
					+ ")生成怪物数为0,无法遇怪");
			return;
		}
		if (req.getMapId() == MmochatConstant.mapId_地府) {
			// 在地府作特殊处理
			List<MmochatMonster> monsterTeam = new ArrayList<MmochatMonster>();

			// 队伍最高等级
			int maxLevel = 0;
			for (MmochatPlayer m : myTeam) {
				if (m.getLevel() > maxLevel) {
					maxLevel = m.getLevel();
				}
			}

			String[] bossBmp = null;

			bossBmp = new String[] { "官", "壮男", "官", "壮男1", "乞丐", "风流才子",
					"动物1", "官", "乞丐", "和尚", "儿童", "儿童", "士兵", "壮男1", "士兵",
					"壮男", "小草", "动物", "鬼", "士兵", "小草", "老头", "凤凰", "凤凰" };

			int nameIndex = MmochatUtil.getRandomValue(bossBmp.length);
			MmochatMonsterFactory monsterFactory = new MmochatMonsterFactory();
			monsterFactory.setBmpType(MmochatRoleBmpType
					.valueOf(bossBmp[nameIndex]));
			monsterFactory.setName("鬼魂");
			monsterFactory.setLevel(maxLevel);
			monsterFactory.setEquipLevel(10);
			monsterFactory.setTeamNum(1);
			monsterFactory.setKillRound(1.2);
			monsterFactory.setPhysical(0.12);
			monsterFactory.setMagic(0.08);
			monsterFactory.setSuperPhysicalAttack(5);
			monsterFactory.setSuperSpritAttack(5);
			monsterFactory.setBossMaxSkillTargetNum(2);
			monsterFactory.setSpeedPointAddType(0);
			MmochatAttackModeOfNormal defaultAttackMode = new MmochatAttackModeOfNormal();
			defaultAttackMode.setPhysicalAttackOpportunity((int) (49));
			defaultAttackMode.setMagicAttackOppotunity((int) (49));
			defaultAttackMode.setLimitOppotunity((int) 2);
			monsterFactory.setAttackMode_normal(defaultAttackMode);

			// 道行在1.5倍之间
			monsterFactory.setDao((int) (1.5 * MmochatBattleService
					.getStandardDao(me.getLevel(), 0)));

			MmochatMonster model = MmochatEquipService
					.setMonsterBattleParam(monsterFactory);
			model.setKillExp(MmochatConstant.daoAwardPerMonsterInDiFu);

			if (MmochatUtil.isInPercent(2)) {
				// 平均每50场战斗遇一次特殊怪:8-12倍
				String[] nameList = new String[] { "五当家", "四当家", "三当家", "二当家",
						"大当家" };
				int index = MmochatUtil.getRandomValue(5);// 0-4
				int expParam = index + 8;// 8-12
				double bloodParam = 1.0 * expParam / 1.4;
				monsterNum = teamNum * 2;
				for (int i = 0; i < monsterNum; i++) {
					int blood = MmochatUtil.getWaveValue(model.getTotalBlood(),
							5);
					int speed = MmochatUtil.getWaveValue(model.getSpeed(), 5);
					MmochatMonster newMonster = model.getClone();
					newMonster.setTotalBlood(blood);
					newMonster.setSpeed(speed);

					if (newMonster != null) {
						newMonster.setTotalBlood((int) (newMonster
								.getTotalBlood() * bloodParam));
						newMonster.setKillExp(newMonster.getKillExp()
								* expParam);
						newMonster.setName(nameList[index]);
						newMonster.setCanBeCatch(false); // 不能捕捉
						monsterTeam.add(newMonster);
					}
				}
			} else {
				// 常规野怪
				for (int i = 0; i < monsterNum; i++) {
					int blood = MmochatUtil.getWaveValue(model.getTotalBlood(),
							5);
					int speed = MmochatUtil.getWaveValue(model.getSpeed(), 5);
					MmochatMonster newMonster = model.getClone();
					newMonster.setTotalBlood(blood);
					newMonster.setSpeed(speed);

					if (newMonster != null) {
						// 2.7%机率出现头领:血量加倍、经验加倍
						double percent = Math.random() * 100;
						if (percent < 1.2) {
							newMonster
									.setTotalBlood(newMonster.getTotalBlood() * 2);
							newMonster.setKillExp((int) (newMonster
									.getKillExp() * 2.5));
							newMonster.setName("小头领");
						} else if (percent < 1.2 + 0.9) {
							newMonster
									.setTotalBlood(newMonster.getTotalBlood() * 3);
							newMonster.setKillExp(newMonster.getKillExp() * 4);
							newMonster.setName("中头领");
						} else if (percent < 2.1 + 0.6) {
							newMonster
									.setTotalBlood(newMonster.getTotalBlood() * 4);
							newMonster.setKillExp(newMonster.getKillExp() * 6);
							newMonster.setName("大头领");
						}
						monsterTeam.add(newMonster);
					}
				}
			}
			// 进入打怪
			MmochatBattleService.enterMonsterPk(me.getMapId(), (byte) me
					.getLine(), myTeam, monsterTeam, MmochatBattleType.地府打怪);
		} else if (req.getMapId() >= MmochatConstant.mapId_地狱二层
				&& req.getMapId() <= MmochatConstant.mapId_地狱十层) {
			// 转生怪物
			int monsterLevel;
			switch (req.getMapId()) {
			case MmochatConstant.mapId_地狱二层:
				monsterLevel = 135;
				break;
			case MmochatConstant.mapId_地狱三层:
				monsterLevel = 145;
				break;
			case MmochatConstant.mapId_地狱四层:
				monsterLevel = 155;
				break;
			case MmochatConstant.mapId_地狱五层:
				monsterLevel = 165;
				break;
			case MmochatConstant.mapId_地狱六层:
				monsterLevel = 175;
				break;
			case MmochatConstant.mapId_地狱七层:
				monsterLevel = 185;
				break;
			case MmochatConstant.mapId_地狱八层:
				monsterLevel = 195;
				break;
			case MmochatConstant.mapId_地狱九层:
				monsterLevel = 205;
				break;
			case MmochatConstant.mapId_地狱十层:
				monsterLevel = 215;
				break;
			default:
				monsterLevel = 215;
				break;
			}
			String[] bossBmp = null;

			bossBmp = new String[] { "官", "壮男", "官", "壮男1", "乞丐", "风流才子",
					"动物1", "官", "乞丐", "和尚", "儿童", "儿童", "士兵", "壮男1", "士兵",
					"壮男", "小草", "动物", "鬼", "士兵", "小草", "老头", "凤凰", "凤凰" };

			int nameIndex = MmochatUtil.getRandomValue(bossBmp.length);

			MmochatMonster model = new MmochatMonster();
			model.setLevel(monsterLevel);
			model.setName("小鬼");
			model.setBmpType(MmochatRoleBmpType.valueOf(bossBmp[nameIndex]));

			// 装载战斗属性
			Map<MmochatRoleAttributeType, Double> attMap = MmochatPetService.monsterBaseAttackData
					.get(monsterLevel);
			if (attMap == null) {
				log.error("怪物属性未找到，monster level=" + monsterLevel);
				return;
			}
			int dao = (int) (attMap.get(MmochatRoleAttributeType.道行倍数) * MmochatBattleService
					.getStandardDao(model.getLevel(), 0));
			model.setDao(dao);
			model.setKillExp((int) ((double) attMap
					.get(MmochatRoleAttributeType.杀死怪物经验)));
			model.setKillSmallMoney((int) ((double) attMap
					.get(MmochatRoleAttributeType.怪物金钱掉落)));
			model.setPhysicalAttack((int) ((double) attMap
					.get(MmochatRoleAttributeType.物伤)));
			model.setSpritAttack((int) ((double) attMap
					.get(MmochatRoleAttributeType.法伤)));
			model.setPhysicalDefend((int) ((double) attMap
					.get(MmochatRoleAttributeType.物防)));
			model.setMagicDefend((int) ((double) attMap
					.get(MmochatRoleAttributeType.法防)));
			model.setTotalBlood((int) ((double) attMap
					.get(MmochatRoleAttributeType.气血)));
			model.setSpeed((int) ((double) attMap
					.get(MmochatRoleAttributeType.速度)));
			model.setPhysicalAvoid((int) ((double) attMap
					.get(MmochatRoleAttributeType.物理闪避)));
			model.setMagicAvoid((int) ((double) attMap
					.get(MmochatRoleAttributeType.法术闪避)));
			model.setPhysicalDeadlyAttack((int) ((double) attMap
					.get(MmochatRoleAttributeType.物理暴击)));
			model.setMagicDeadlyAttack((int) ((double) attMap
					.get(MmochatRoleAttributeType.法术暴击)));
			model.setPhysicalDeadlyAttackDefend((int) ((double) attMap
					.get(MmochatRoleAttributeType.物理暴击抵抗)));
			model.setMagicDeadlyAttackDefend((int) ((double) attMap
					.get(MmochatRoleAttributeType.法术暴击抵抗)));
			model.setPhysicalDoubleAttack((int) ((double) attMap
					.get(MmochatRoleAttributeType.物理致命一击)));
			model.setMagicDoubleAttack((int) ((double) attMap
					.get(MmochatRoleAttributeType.法术致命一击)));
			model.setPhysicalDoubleAttackDefend((int) ((double) attMap
					.get(MmochatRoleAttributeType.物理致命抵抗)));
			model.setMagicDoubleAttackDefend((int) ((double) attMap
					.get(MmochatRoleAttributeType.法术致命抵抗)));
			model.setPhysicalDefendIgnore((int) ((double) attMap
					.get(MmochatRoleAttributeType.物理破防)));
			model.setMagicDefendIgnore((int) ((double) attMap
					.get(MmochatRoleAttributeType.法术破防)));
			model.setAntiSeal((int) ((double) attMap
					.get(MmochatRoleAttributeType.封印抵抗)));
			model.setAntiFreeze((int) ((double) attMap
					.get(MmochatRoleAttributeType.冰冻抵抗)));
			model.setAntiConfuse((int) ((double) attMap
					.get(MmochatRoleAttributeType.混乱抵抗)));
			model.setIgnoreAntiSeal((int) ((double) attMap
					.get(MmochatRoleAttributeType.忽视封印抵抗)));
			model.setIgnoreAntiFreeze((int) ((double) attMap
					.get(MmochatRoleAttributeType.忽视冰冻抵抗)));
			model.setIgnoreAntiConfuse((int) ((double) attMap
					.get(MmochatRoleAttributeType.忽视混乱抵抗)));
			model.setStrengthenSeal((int) ((double) attMap
					.get(MmochatRoleAttributeType.强化封印)));
			model.setStrengthenFreeze((int) ((double) attMap
					.get(MmochatRoleAttributeType.强化冰冻)));
			model.setStrengthenConfuse((int) ((double) attMap
					.get(MmochatRoleAttributeType.强化混乱)));
			model.setPhysicalDefendPercent((int) ((double) attMap
					.get(MmochatRoleAttributeType.物理免疫)));
			model.setMagicDefendPercent((int) ((double) attMap
					.get(MmochatRoleAttributeType.法术免疫)));
			model.setAntiGodSkill((int) ((double) attMap
					.get(MmochatRoleAttributeType.抗雷)));
			model.setAntiHumanSkill((int) ((double) attMap
					.get(MmochatRoleAttributeType.抗水)));
			model.setAntiDevilSkill((int) ((double) attMap
					.get(MmochatRoleAttributeType.抗毒)));
			model.setIgnoreAntiGodSkill((int) ((double) attMap
					.get(MmochatRoleAttributeType.忽视抗雷)));
			model.setIgnoreAntiHumanSkill((int) ((double) attMap
					.get(MmochatRoleAttributeType.忽视抗水)));
			model.setIgnoreAntiDevilSkill((int) ((double) attMap
					.get(MmochatRoleAttributeType.忽视抗毒)));
			model.setSuperPhysicalAttack((int) ((double) attMap
					.get(MmochatRoleAttributeType.神圣物理伤害)));
			model.setSuperSpritAttack((int) ((double) attMap
					.get(MmochatRoleAttributeType.神圣法术伤害)));

			List<MmochatMonster> monsterTeam = new ArrayList<MmochatMonster>();

			if (MmochatUtil.isInPercent(4)) {
				// 平均每25场战斗遇一次特殊怪:8-12倍
				String[] nameList = new String[] { "五当家", "四当家", "三当家", "二当家",
						"大当家" };
				int index = MmochatUtil.getRandomValue(5);// 0-4
				int expParam = index + 8;// 8-12
				double bloodParam = 1.0 * expParam / 1.4;
				monsterNum = teamNum * 2;
				for (int i = 0; i < monsterNum; i++) {
					int blood = MmochatUtil.getWaveValue(model.getTotalBlood(),
							5);
					int speed = MmochatUtil.getWaveValue(model.getSpeed(), 5);
					MmochatMonster newMonster = model.getClone();
					newMonster.setTotalBlood(blood);
					newMonster.setSpeed(speed);

					if (newMonster != null) {
						newMonster.setTotalBlood((int) (newMonster
								.getTotalBlood() * bloodParam));
						newMonster.setKillExp(newMonster.getKillExp()
								* expParam);
						newMonster.setName(nameList[index]);
						newMonster.setCanBeCatch(false); // 不能捕捉
						monsterTeam.add(newMonster);
					}
				}
			} else {
				// 常规野怪
				for (int i = 0; i < monsterNum; i++) {
					int blood = MmochatUtil.getWaveValue(model.getTotalBlood(),
							5);
					int speed = MmochatUtil.getWaveValue(model.getSpeed(), 5);
					MmochatMonster newMonster = model.getClone();
					newMonster.setTotalBlood(blood);
					newMonster.setSpeed(speed);
					newMonster.setCanBeCatch(false); // 不能捕捉

					// 2.7%机率出现头领:血量加倍、经验加倍
					// 0.7%机率出现宝宝
					double percent = Math.random() * 100;
					if (percent < 1.2) {
						newMonster
								.setTotalBlood(newMonster.getTotalBlood() * 2);
						newMonster
								.setKillExp((int) (newMonster.getKillExp() * 2.5));
						newMonster.setName("小头领");
					} else if (percent < 1.2 + 0.9) {
						newMonster
								.setTotalBlood(newMonster.getTotalBlood() * 3);
						newMonster.setKillExp(newMonster.getKillExp() * 4);
						newMonster.setName("中头领");
					} else if (percent < 2.1 + 0.6) {
						newMonster
								.setTotalBlood(newMonster.getTotalBlood() * 4);
						newMonster.setKillExp(newMonster.getKillExp() * 6);
						newMonster.setName("大头领");
					}
					monsterTeam.add(newMonster);
				}
			}

			// 进入打怪
			MmochatBattleService.enterMonsterPk(me.getMapId(), (byte) me
					.getLine(), myTeam, monsterTeam);

		} else {
			// 常规野怪
			if (!curMap.isHasMonster()) {
				log.debug("玩家" + me.getName() + "(skyid=" + me.getSkyId()
						+ ")在非遇怪地图,无法遇怪;mapId=" + curMap.getMapId());
				return;
			}
			if (curMap.getMonster().size() == 0) {
				log.debug("玩家" + me.getName() + "(skyid=" + me.getSkyId()
						+ ")在非遇怪地图,无法遇怪;mapId=" + curMap.getMapId());
				return;
			}

			List<MmochatMonster> monsterTeam = new ArrayList<MmochatMonster>();

			if (MmochatUtil.isInPercent(4)) {
				// 平均每25场战斗遇一次特殊怪:8-12倍
				String[] nameList = new String[] { "五当家", "四当家", "三当家", "二当家",
						"大当家" };
				int index = MmochatUtil.getRandomValue(5);// 0-4
				int expParam = index + 8;// 8-12
				double bloodParam = 1.0 * expParam / 1.4;
				monsterNum = teamNum * 2;
				for (int i = 0; i < monsterNum; i++) {
					MmochatMonster newMonster = curMap.getRandMonster();
					if (newMonster != null) {
						newMonster.setTotalBlood((int) (newMonster
								.getTotalBlood() * bloodParam));
						newMonster.setKillExp(newMonster.getKillExp()
								* expParam);
						newMonster.setName(nameList[index]);
						newMonster.setCanBeCatch(false); // 不能捕捉
						monsterTeam.add(newMonster);
					}
				}
			} else {
				// 常规野怪
				for (int i = 0; i < monsterNum; i++) {
					MmochatMonster newMonster = curMap.getRandMonster();
					if (newMonster != null) {
						// 2.7%机率出现头领:血量加倍、经验加倍
						// 0.7%机率出现宝宝
						// 北郊:4%机率出现<猛虎药兽>
						// 西郊:2%机率出现<仙草药兽>
						// 东郊:2%机率出现<古树药兽>
						double percent = Math.random() * 100;
						if (percent < 1.2) {
							newMonster
									.setTotalBlood(newMonster.getTotalBlood() * 2);
							newMonster.setKillExp((int) (newMonster
									.getKillExp() * 2.5));
							newMonster.setName("小头领");
						} else if (percent < 1.2 + 0.9) {
							newMonster
									.setTotalBlood(newMonster.getTotalBlood() * 3);
							newMonster.setKillExp(newMonster.getKillExp() * 4);
							newMonster.setName("中头领");
						} else if (percent < 2.1 + 0.6) {
							newMonster
									.setTotalBlood(newMonster.getTotalBlood() * 4);
							newMonster.setKillExp(newMonster.getKillExp() * 6);
							newMonster.setName("大头领");
						} else if (percent < 2.7 + 0.7) {
							// 宝宝血量1点；根据血量判定为宝宝
							newMonster.setTotalBlood(1);
							newMonster.setName("宝宝");
						} else {
							if (curMap.getMapId() == MmochatConstant.mapId_北郊) {
								if (percent < 3.4 + 4) {
									// 虎
									if (newMonster.getBmpType() == MmochatRoleBmpType.动物) {
										newMonster.setTotalBlood(2);
										newMonster.setName("药兽");
									}
								}
							} else if (curMap.getMapId() == MmochatConstant.mapId_西郊) {
								if (percent < 3.4 + 2) {
									// 草
									if (newMonster.getBmpType() == MmochatRoleBmpType.小草) {
										newMonster.setTotalBlood(2);
										newMonster.setName("药兽");
									}
								}
							} else if (curMap.getMapId() == MmochatConstant.mapId_东郊) {
								if (percent < 3.4 + 2) {
									// 树
									if (newMonster.getBmpType() == MmochatRoleBmpType.树) {
										newMonster.setTotalBlood(2);
										newMonster.setName("药兽");
									}
								}
							}
						}
						monsterTeam.add(newMonster);
					}
				}
			}

			// 进入打怪
			MmochatBattleService.enterMonsterPk(me.getMapId(), (byte) me
					.getLine(), myTeam, monsterTeam);
		}
		log.debug("玩家" + me.getName() + "(skyid=" + me.getSkyId() + ")遇怪");
	}
}
